package logger

import (
	"bytes"
	"fmt"
	"github.com/natefinch/lumberjack"
	"github.com/sirupsen/logrus"
	log "github.com/sirupsen/logrus"
	"io"
	"os"
	"path/filepath"
	"vpn/config"
)

type multiWriter struct {
	writers []io.Writer
}

// 实现 io.Writer 接口的 Write 方法
func (mw *multiWriter) Write(p []byte) (n int, err error) {
	for _, w := range mw.writers {
		n, err = w.Write(p)
		if err != nil {
			return n, err
		}
	}
	return len(p), nil
}

// LogFormatter 结构体
type LogFormatter struct{}

// Format 方法
func (f *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	var b *bytes.Buffer
	if entry.Buffer != nil {
		b = entry.Buffer
	} else {
		b = new(bytes.Buffer)
	}

	timestamp := entry.Time.Format("2006-01-02 15:04:05.000")
	var msg string

	if entry.HasCaller() {
		//fName := filepath.Base(entry.Caller.File)
		msg = fmt.Sprintf("[%s][%s] %s[%s:%d]\n",
			//timestamp, entry.Level.String(), entry.Message, fName, entry.Caller.Line)
			timestamp, entry.Level.String(), entry.Message, entry.Caller.File, entry.Caller.Line)
	} else {
		msg = fmt.Sprintf("[%s][%s] %s\n",
			timestamp, entry.Level.String(), entry.Message)
	}

	b.WriteString(msg)
	return b.Bytes(), nil
}

func newRotateLogs(conf config.LogConfig) io.Writer {
	return &lumberjack.Logger{
		Filename:   conf.FilePath,
		MaxSize:    int(conf.Size), // MB
		MaxBackups: int(conf.Count),
		MaxAge:     0, // 不限制日志文件的年龄
		Compress:   false,
	}
}

func InitLogger(conf config.LogConfig) {
	// 确保日志目录存在
	logDir := filepath.Dir(conf.FilePath)
	if _, err := os.Stat(logDir); os.IsNotExist(err) {
		err = os.MkdirAll(logDir, os.ModePerm)
		if err != nil {
			fmt.Printf("failed to create log directory: %v", err)
		}
	}

	// 创建文件输出
	fileWriter := newRotateLogs(conf)
	if conf.IsToStdout {
		writers := []io.Writer{
			fileWriter,
			os.Stdout, // 标准输出
		}
		multiWriter := &multiWriter{writers: writers}
		log.SetOutput(multiWriter)
	} else {
		log.SetOutput(fileWriter)
	}

	logLevel := log.InfoLevel
	switch conf.Level {
	case "Debug":
		logLevel = log.DebugLevel
	case "Warn":
		logLevel = log.WarnLevel
	case "Info":
		logLevel = log.InfoLevel
	case "Error":
		logLevel = log.ErrorLevel
	}
	log.SetLevel(logLevel)
	log.SetFormatter(&LogFormatter{})
	//log.SetFormatter(&logrus.TextFormatter{})
	log.SetReportCaller(true)

}
